#include "MResidentAlert.h"

#include <QHBoxLayout>

MResidentAlert::MResidentAlert(IconType type, WindowStyle style, QWidget *parent, int32_t maxWidth) : QWidget{parent}, iconType_(type), maxWidth_(maxWidth)
{
    setFocusPolicy(Qt::NoFocus);
    setAttribute(Qt::WA_TranslucentBackground, true);
    setAttribute(Qt::WA_TransparentForMouseEvents);
    if (style == STYLE_POPUP)
    {
        this->setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint);
    }

    rootLayout_ = new QHBoxLayout();
    frameLayout_ = new QHBoxLayout();
    frameBackground_ = new QFrame(this);
    labelIcon_ = new QLabel(this);
    labelContent_ = new QLabel(this);

    frameBackground_->setObjectName("frame_background");

    labelIcon_->setObjectName("label_icon");
    labelIcon_->setFixedSize(20, 20);

    labelContent_->setObjectName("label_content");
    labelContent_->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);

    frameLayout_->setContentsMargins(46, 5, 46, 5);
    frameLayout_->setSpacing(4);
    frameLayout_->addWidget(labelIcon_);
    frameLayout_->addWidget(labelContent_);
    frameBackground_->setLayout(frameLayout_);

    rootLayout_->setMargin(0);
    rootLayout_->setSpacing(0);
    rootLayout_->addWidget(frameBackground_);
    this->setLayout(rootLayout_);

    refreshLayout();
}

void MResidentAlert::setDwellTime(uint64_t duration)
{
    dwellDuration_ = duration;
}

void MResidentAlert::setIntoAnimation(AnimationDirection direction, uint64_t duration)
{
    intoAnimationDirection_ = direction;
    intoAnimationDuration_ = duration;
}

void MResidentAlert::setExitAnimation(AnimationDirection direction, uint64_t duration)
{
    exitAnimationDirection_ = direction;
    exitAnimationDuration_ = duration;
}

void MResidentAlert::updateMsgConfig(IconType type, int32_t maxWidth)
{
    iconType_ = type;
    maxWidth_ = maxWidth;
    refreshLayout();
}

void MResidentAlert::showEvent(QShowEvent *event)
{
    QWidget::showEvent(event);
    reset();

    if (dwellDuration_ > 0)
    {
        dwellTime_ = new QTimer(this);
        connect(dwellTime_, &QTimer::timeout, this, &MResidentAlert::onDwellTimeout, Qt::UniqueConnection);
        dwellTime_->setInterval(dwellDuration_);
        dwellTime_->start();
    }
    if (intoAnimationDirection_ != ANIMATION_NONE)
    {
        createIntoAnimation(intoAnimationDirection_, intoAnimationDuration_);
        connect(intoAnimation_, &QPropertyAnimation::finished, [this]() {
            intoAnimation_->deleteLater();
            intoAnimation_ = nullptr;
        });
        intoAnimation_->start(QAbstractAnimation::DeleteWhenStopped);
    }
}

void MResidentAlert::hideEvent(QHideEvent *event)
{
    QWidget::hideEvent(event);
    reset();
}

void MResidentAlert::closeEvent(QCloseEvent *event)
{
    QWidget::closeEvent(event);
    reset();
}

void MResidentAlert::setMsgContent(const QString &msg)
{
    if (!labelContent_)
    {
        return;
    }
    labelContent_->setText(msg);

    int left, top, right, bottom;
    frameLayout_->getContentsMargins(&left, &top, &right, &bottom);
    int spacing = frameLayout_->spacing();
    int labelWidth = maxWidth_ - left - right - labelIcon_->width() - spacing;

    QFontMetrics metrics = labelContent_->fontMetrics();
    int textWidth = metrics.horizontalAdvance(msg);

    if (maxWidth_ > -1 && textWidth > labelWidth) {
        labelContent_->setWordWrap(true);
        QRect newRect = metrics.boundingRect(QRect(0, 0, labelWidth, metrics.height()), Qt::TextWordWrap, msg);
        setFixedSize(maxWidth_, newRect.height() + top + bottom);
    } else {
        labelContent_->setWordWrap(false);
        int width = left + right + labelIcon_->width() + spacing + textWidth;
        int height = top + bottom + labelIcon_->height();
        setFixedSize(width, height);
    }
}

void MResidentAlert::refreshLayout()
{
    switch (iconType_)
    {
    case ICON_INFO:
        frameBackground_->setStyleSheet(R"(MResidentAlert QFrame#frame_background { background-color: #303133;})");
        labelIcon_->setStyleSheet(R"(MResidentAlert QLabel#label_icon { border-image: url(:/Image/Resource/Image/msgInfoIcon.png);})");
        labelContent_->setStyleSheet(R"(MResidentAlert QLabel#label_content { color: #FFFFFF; })");
        break;
    case ICON_WARNING:
        frameBackground_->setStyleSheet(R"(MResidentAlert QFrame#frame_background { background-color: #FFE9D6;})");
        labelIcon_->setStyleSheet(R"(MResidentAlert QLabel#label_icon { border-image: url(:/Image/Resource/Image/msgWarningIcon.png);})");
        labelContent_->setStyleSheet(R"(MResidentAlert QLabel#label_content { color: #303133; })");
        break;
    case ICON_SUCCESSFUL:
        frameBackground_->setStyleSheet(R"(MResidentAlert QFrame#frame_background { background-color: #D6FFE6;})");
        labelIcon_->setStyleSheet(R"(MResidentAlert QLabel#label_icon { border-image: url(:/Image/Resource/Image/msgFailedIcon.png);})");
        labelContent_->setStyleSheet(R"(MResidentAlert QLabel#label_content { color: #303133; })");
        break;
    case ICON_FAILED:
        frameBackground_->setStyleSheet(R"(MResidentAlert QFrame#frame_background { background-color: #FFDDDD;})");
        labelIcon_->setStyleSheet(R"(MResidentAlert QLabel#label_icon { border-image: url(:/Image/Resource/Image/msgSuccessfulIcon.png);})");
        labelContent_->setStyleSheet(R"(MResidentAlert QLabel#label_content { color: #303133; })");
        break;
    default:
        frameBackground_->setStyleSheet(R"(MResidentAlert QFrame#frame_background { background-color: #303133;})");
        labelIcon_->setStyleSheet(R"(MResidentAlert QLabel#label_icon { border-image: url(:/Image/Resource/Image/msgInfoIcon.png);})");
        labelContent_->setStyleSheet(R"(MResidentAlert QLabel#label_content { color: #FFFFFF; })");
        break;
    }
}

void MResidentAlert::reset()
{
    if (dwellTime_ && dwellTime_->isActive())
    {
        dwellTime_->stop();
    }
    if (intoAnimation_ && intoAnimation_->state() == QAbstractAnimation::Running)
    {
        intoAnimation_->stop();
    }
    if (intoAnimation_ && exitAnimation_->state() == QAbstractAnimation::Running)
    {
        exitAnimation_->stop();
    }
}

void MResidentAlert::createIntoAnimation(AnimationDirection direction, uint64_t duration)
{
    intoAnimation_ = new QPropertyAnimation(frameBackground_, "geometry");
    intoAnimation_->setDuration(duration); // Duration of the animation in milliseconds
    switch (direction)
    {
    case ANIMATION_LEFT_TO_RIGHT:
        intoAnimation_->setStartValue(QRect(-width(), 0, width(), height()));
        intoAnimation_->setEndValue(QRect(0, 0, width(), height()));
        break;
    case ANIMATION_TOP_TO_DOWN:
        intoAnimation_->setStartValue(QRect(0, -height(), width(), height()));
        intoAnimation_->setEndValue(QRect(0, 0, width(), height()));
        break;
    case ANIMATION_RIGHT_TO_LEFT:
        intoAnimation_->setStartValue(QRect(width(), 0, width(), height()));
        intoAnimation_->setEndValue(QRect(0, 0, width(), height()));
        break;
    case ANIMATION_DOWN_TO_TOP:
        intoAnimation_->setStartValue(QRect(0, height(), width(), height()));
        intoAnimation_->setEndValue(QRect(0, 0, width(), height()));
        break;
    case ANIMATION_NONE:
    default:
        break;
    }
}

void MResidentAlert::createExitAnimation(AnimationDirection direction, uint64_t duration)
{
    exitAnimation_ = new QPropertyAnimation(frameBackground_, "geometry");
    exitAnimation_->setDuration(duration); // Duration of the animation in milliseconds
    switch (direction)
    {
    case ANIMATION_LEFT_TO_RIGHT:
        exitAnimation_->setStartValue(QRect(0, 0, width(), height()));
        exitAnimation_->setEndValue(QRect(width(), 0, width(), height()));
        break;
    case ANIMATION_TOP_TO_DOWN:
        exitAnimation_->setStartValue(QRect(0, 0, width(), height()));
        exitAnimation_->setEndValue(QRect(0, height(), width(), height()));
        break;
    case ANIMATION_RIGHT_TO_LEFT:
        exitAnimation_->setStartValue(QRect(0, 0, width(), height()));
        exitAnimation_->setEndValue(QRect(-width(), 0, width(), height()));
        break;
    case ANIMATION_DOWN_TO_TOP:
        exitAnimation_->setStartValue(QRect(0, 0, width(), height()));
        exitAnimation_->setEndValue(QRect(0, -height(), width(), height()));
        break;
    case ANIMATION_NONE:
    default:
        break;
    }
}

void MResidentAlert::onDwellTimeout()
{
    if (exitAnimationDirection_ != ANIMATION_NONE)
    {
        createExitAnimation(exitAnimationDirection_, exitAnimationDuration_);
        connect(exitAnimation_, &QPropertyAnimation::finished, [this]() { emit sgnAutoHidden(); });
        exitAnimation_->start(QAbstractAnimation::DeleteWhenStopped);
    }
    else
    {
        emit sgnAutoHidden();
    }
}
